import logging
from pathlib import Path

import pytz
from aiogram import Bot
from arq import cron

from src.application.order.service import OrderService
from src.application.user.service import UserService
from src.config import load_config
from src.infrastructure.db.main import build_sa_engine, build_sa_session_factory
from src.infrastructure.db.repositories import (
    BotSettingsReaderImpl,
    CategoryReaderImpl,
    OrderReaderImpl,
    OrderRepoImpl,
    ProxyReaderImpl,
    ProxyRepoImpl,
    UserReaderImpl,
    UserRepoImpl,
)
from src.infrastructure.db.uow import SQLAlchemyUoW
from src.infrastructure.db.uow.uow import build_uow
from src.infrastructure.logger import configure_logging
from src.presentation.tg_bot.__main__ import BOTFOLDER
from src.presentation.tg_bot.services.locale import configure_localizator
from src.presentation.tg_bot.worker.jobs import (
    archiving_expired_orders,
    autorenew_orders,
    change_authorization_type_job,
    change_proxy,
    check_proxy,
    check_proxy_speed_job,
    generate_vpn_config_job,
    notify_expiring_orders,
    notify_users,
    proxy_checker,
    update_rotation_type,
)

config = load_config()

logger = logging.getLogger(__name__)


def generate_run_time(x: int, start: int, end: int) -> set:
    """Generate set with x period between start and end interval"""
    return {*list(range(start, end, x))}


async def startup(ctx):
    configure_logging()
    logger.info("Starting worker")
    engine = build_sa_engine(config.db)
    ctx["sessionmaker"] = build_sa_session_factory(engine)
    ctx["config"] = config
    ctx["bot"] = Bot(token=config.tg_bot.token, parse_mode="HTML")
    ctx["fluent"] = configure_localizator(BOTFOLDER / Path("locales/"))


async def on_job_start(ctx):
    async with ctx["sessionmaker"]() as session:
        uow = build_uow(session)
        ctx["session"] = session
        ctx["uow"] = uow
        ctx["user_service"] = UserService(uow=uow)
        ctx["order_service"] = OrderService(uow=uow)


async def shutdown(ctx):
    await ctx["bot"].session.close()


class WorkerSettings:
    functions = [
        notify_users,
        autorenew_orders,
        notify_expiring_orders,
        archiving_expired_orders,
        change_authorization_type_job,
        update_rotation_type,
        proxy_checker,
        check_proxy,
        change_proxy,
        check_proxy_speed_job,
        generate_vpn_config_job,
    ]
    on_startup = startup
    on_shutdown = shutdown
    on_job_start = on_job_start
    timezone = pytz.timezone("Europe/Moscow")
    cron_jobs = [
        cron(autorenew_orders, minute=generate_run_time(7, 0, 59), max_tries=2),
        cron(archiving_expired_orders, minute=generate_run_time(7, 0, 59), max_tries=2, run_at_startup=True),
        cron(
            notify_expiring_orders,
            minute=generate_run_time(5, 0, 59),
            max_tries=2,
        ),
        cron(
            proxy_checker,
            minute=generate_run_time(6, 0, 59),
            max_tries=2,
        ),
    ]
    redis_settings = config.redis.pool_settings
